package com.components.base.view.tiktok

import android.content.Context
import android.graphics.*
import android.graphics.drawable.NinePatchDrawable
import android.util.AttributeSet
import android.widget.ImageView
import com.blankj.utilcode.util.ConvertUtils
import com.components.base.R
import kotlin.math.min

class TikTokCircleMusicView constructor(
    context: Context,
    attrs: AttributeSet? = null,
    defStyleAttr: Int = 0
) :
    ImageView(context, attrs, defStyleAttr) {
    private var mDefaultSize = 0
    private var mProgressWidth = 0

    // 进度槽颜色
    private var mProgressSlotColor = 0

    // 缓冲进度颜色
    private var mProgressBufferColor = 0

    // 进度颜色
    private var mProgressColor = 0
    private var mSize = 0
    private var mBufferProgress = 0f
    private var mProgress = 0f
    private var mDegree = 0f

    // 遮罩相关
    private var mShadeBitmap: Bitmap? = null
    private var mPaint: Paint? = null

    // 进度相关
    private var mProgressPaint: Paint? = null
    private var mProgressRect: RectF? = null
    private fun init(context: Context, attrs: AttributeSet?) {
        mDefaultSize = ConvertUtils.dp2px(DEFAULT_DEFAULT_SIZE.toFloat())
        val defaultBorderWidth = ConvertUtils.dp2px(DEFAULT_BORDER_WIDTH.toFloat())
        val ta = context.obtainStyledAttributes(attrs, R.styleable.tiktokMusicView, 0, 0)
        try {
            mProgressWidth = ta.getDimensionPixelOffset(
                R.styleable.tiktokMusicView_tiktok_music_view_progress_width,
                defaultBorderWidth
            )
            mProgressBufferColor = ta.getColor(
                R.styleable.tiktokMusicView_tiktok_music_view_progress_slot_color,
                Color.LTGRAY
            )
            mProgressSlotColor = ta.getColor(
                R.styleable.tiktokMusicView_tiktok_music_view_progress_buffer_color,
                Color.GRAY
            )
            mProgressColor = ta.getColor(
                R.styleable.tiktokMusicView_tiktok_music_view_progress_color,
                Color.YELLOW
            )
        } finally {
            ta.recycle()
        }
        mPaint = Paint(Paint.ANTI_ALIAS_FLAG)
        mPaint!!.xfermode = PorterDuffXfermode(PorterDuff.Mode.DST_IN)
        mPaint!!.isFilterBitmap = true
        mProgressPaint = Paint(Paint.ANTI_ALIAS_FLAG)
        mProgressPaint!!.strokeWidth = mProgressWidth.toFloat()
        mProgressPaint!!.style = Paint.Style.STROKE
    }

    override fun onDraw(canvas: Canvas) {
        val drawable = drawable
        if (drawable == null || drawable is NinePatchDrawable) {
            return
        }
        val layer =
            canvas.saveLayer(0f, 0f, mSize.toFloat(), mSize.toFloat(), null, Canvas.ALL_SAVE_FLAG)
        canvas.rotate(mDegree, (mSize / 2).toFloat(), (mSize / 2).toFloat())
        drawable.setBounds(0, 0, mSize, mSize)
        // 原图
        drawable.draw(canvas)
        if (mShadeBitmap == null || mShadeBitmap!!.isRecycled) {
            mShadeBitmap = createShadeBitmap()
        }
        // 遮罩
        canvas.drawBitmap(mShadeBitmap!!, 0f, 0f, mPaint)
        canvas.restoreToCount(layer)
        // 进度槽
        mProgressPaint!!.color = mProgressSlotColor
        canvas.drawArc(mProgressRect!!, 0f, 360f, false, mProgressPaint!!)
        // 缓冲进度
        mProgressPaint!!.color = mProgressBufferColor
        canvas.drawArc(mProgressRect!!, -90f, mBufferProgress, false, mProgressPaint!!)
        // 进度
        mProgressPaint!!.color = mProgressColor
        canvas.drawArc(mProgressRect!!, -90f, mProgress, false, mProgressPaint!!)
    }

    override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
        val measureWidth = measureDimension(mDefaultSize, widthMeasureSpec)
        val measureHeight = measureDimension(mDefaultSize, heightMeasureSpec)
        setMeasuredDimension(measureWidth, measureHeight)
    }

    override fun onSizeChanged(w: Int, h: Int, oldw: Int, oldh: Int) {
        super.onSizeChanged(w, h, oldw, oldh)
        mSize = min(w, h)
        // 进度条范围
        val halfBoardWidth = mProgressWidth / 2
        mProgressRect = RectF(
            halfBoardWidth.toFloat(),
            halfBoardWidth.toFloat(),
            (mSize - halfBoardWidth).toFloat(),
            (mSize - halfBoardWidth).toFloat()
        )
    }

    fun setProgress(progress: Float) {
        mProgress = progress
        invalidate()
    }

    fun setBufferProgress(progress: Float) {
        mBufferProgress = progress
        invalidate()
    }

    override fun setImageResource(resId: Int) {
        super.setImageResource(resId)
        mDegree = 0f
    }

    override fun setImageBitmap(bm: Bitmap) {
        super.setImageBitmap(bm)
        mDegree = 0f
    }

    private fun measureDimension(defaultSize: Int, measureSpec: Int): Int {
        val result: Int
        val specMode = MeasureSpec.getMode(measureSpec)
        val specSize = MeasureSpec.getSize(measureSpec)
        result = when (specMode) {
            MeasureSpec.EXACTLY -> {
                specSize
            }
            MeasureSpec.AT_MOST -> {
                min(defaultSize, specSize)
            }
            else -> {
                defaultSize
            }
        }
        return result
    }

    private fun setDegree(degree: Float) {
        mDegree = degree
        invalidate()
    }

    fun startRotate() {
        mDegree++
        if (mDegree > 360) {
            mDegree = 0f
        }
        setDegree(mDegree)
    }

    /**
     * 弄个圆形遮罩图片,XferMode只能要图片，画别的不行
     */
    private fun createShadeBitmap(): Bitmap {
        val bitmap = Bitmap.createBitmap(mSize, mSize, Bitmap.Config.ARGB_8888)
        val canvas = Canvas(bitmap)
        val paint = Paint(Paint.ANTI_ALIAS_FLAG)
        paint.isFilterBitmap = true
        val f = RectF(
            mProgressWidth.toFloat(),
            mProgressWidth.toFloat(),
            (mSize - mProgressWidth).toFloat(),
            (mSize - mProgressWidth).toFloat()
        )
        canvas.drawOval(f, paint)
        return bitmap
    }

    companion object {
        private const val DEFAULT_BORDER_WIDTH = 2 //dp
        private const val DEFAULT_DEFAULT_SIZE = 45 //dp
    }

    init {
        init(context, attrs)
    }
}
